package com.storm.classes.loader
{
	import com.storm.classes.pool.Pool;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	import mx.core.ClassFactory;
	
	public class DataLoader extends EventDispatcher {
		
		private static const LOADER_POOL:Pool = new Pool(URLLoader);
		
		public function DataLoader(data:Object = null, loadedHandler:Function = null, urlField:String = "url", dataField:String = "data") {
			super();
			if (data) {
				if (data is Array) {
					this.loadDatas(data as Array, loadedHandler, urlField, dataField);
				} else {
					if (data[urlField] is Array) {
						this.loadDataList(data, loadedHandler, urlField, dataField);
					} else {
						this.loadData(data, loadedHandler, urlField, dataField);
					}
				}
			}
		}
		
		protected function processIOError(error:IOErrorEvent):void {
			
		}
		
		protected function processSecurityError(error:SecurityErrorEvent):void {
			
		}
		
		private function loadData(data:Object, loadedHandler:Function = null, urlField:String = "url", dataField:String = "data"):void {
			
			function loadCompleteHandler(event:Event):void {
				var loader:URLLoader = (event.currentTarget as URLLoader);
				data[dataField] = loader.data;
				if (loadedHandler === null) {
					dispatchEvent(new Event(Event.COMPLETE));
				} else {
					loadedHandler(data);
				}
				loader.removeEventListener(Event.COMPLETE, loadCompleteHandler);
				loader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				LOADER_POOL.freeItem = loader;
			}
			
			function ioErrorHandler(event:IOErrorEvent):void {
				processIOError(event);
				var loader:URLLoader = (event.currentTarget as URLLoader);
				loader.removeEventListener(Event.COMPLETE, loadCompleteHandler);
				loader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				LOADER_POOL.freeItem = loader;
			}
			
			function securityErrorHandler(event:SecurityErrorEvent):void {
				processSecurityError(event);
				var loader:URLLoader = (event.currentTarget as URLLoader);
				loader.removeEventListener(Event.COMPLETE, loadCompleteHandler);
				loader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				LOADER_POOL.freeItem = loader;
			}
			
			var url:String = data[urlField];
			if (!url || url == "") {
				loadedHandler(data);
				return;
			}
			var loader:URLLoader = LOADER_POOL.freeItem;
			loader.addEventListener(Event.COMPLETE, loadCompleteHandler);
			loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			loader.load(new URLRequest(url));
		}
		
		private function loadImageIndex(data:Object, index:int, loadedHandler:Function, urlField:String, datas:Array):void {
			
			function loadCompleteHandler(event:Event):void {
				var loader:URLLoader = (event.currentTarget as URLLoader);
				datas[index] = loader.data;
				if (loadedHandler === null) {
					dispatchEvent(new Event(Event.COMPLETE));
				} else {
					loadedHandler(data);
				}
				loader.removeEventListener(Event.COMPLETE, loadCompleteHandler);
				loader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				LOADER_POOL.freeItem = loader;
			}
			
			function ioErrorHandler(event:IOErrorEvent):void {
				processIOError(event);
				var loader:URLLoader = (event.currentTarget as URLLoader);
				loader.removeEventListener(Event.COMPLETE, loadCompleteHandler);
				loader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				LOADER_POOL.freeItem = loader;
			}
			
			function securityErrorHandler(event:SecurityErrorEvent):void {
				processSecurityError(event);
				var loader:URLLoader = (event.currentTarget as URLLoader);
				loader.removeEventListener(Event.COMPLETE, loadCompleteHandler);
				loader.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				LOADER_POOL.freeItem = loader;
			}
			
			var url:String = data[urlField][index];
			if (!url || url == "") {
				loadedHandler(data);
				return;
			}
			var loader:URLLoader = LOADER_POOL.freeItem;
			loader.addEventListener(Event.COMPLETE, loadCompleteHandler);
			loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			loader.load(new URLRequest(url));
		}
		
		private function loadDatas(datas:Array, loadedHandler:Function = null, urlField:String = "url", dataField:String = "data"):void {
			var count:int = datas.length;
			for each (var data:Object in datas) {
				this.loadData(data, function(data:Object):void {
					count --;
					if (count == 0) {
						if (loadedHandler === null) {
							dispatchEvent(new Event(Event.COMPLETE));
						} else {
							loadedHandler(datas);
						}
					}
				}, urlField, dataField);
			}
		}
		
		private function loadDataList(data:Object, loadedHandler:Function = null, urlField:String = "url", dataField:String = "data"):void {
			var datas:Array = data[urlField] as Array;
			
			var count:int = datas.length;
			var datas:Array = [];
			for (var i:int = 0; i < count; i++) {
				this.loadImageIndex(data, i, function(data:Object):void {
					count --;
					if (count == 0) {
						data[dataField] = datas;
						if (loadedHandler === null) {
							dispatchEvent(new Event(Event.COMPLETE));
						} else {
							loadedHandler(data);
						}
					}
				}, urlField, datas);
			}
		}
	}
}